#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <config.h>
#include <network.h>
#include "tools.h"

NetWork* create_network(NetWork* cmd_nw)
{
	NetWork* data_nw = NULL;
	for(;;)
	{
		uint16_t port = rand() % 30000 + 1024;
		data_nw = open_network('s',FILE_MODE,SERVER_IP,port);
		if(NULL != data_nw)
		{
			char cmd_buf[256] = {};
			sprintf(cmd_buf,"data port:%hu",port);
			printf("cmd_buf:%s\n",cmd_buf);
			nsend(cmd_nw,cmd_buf,strlen(cmd_buf)+1);
			break;
		}
	}
	return data_nw;
}

void list_server(NetWork* cmd_nw,char* cmd_buf)
{
	char data_buf[1024] = {};
	NetWork* data_nw = NULL , *con_nw = NULL;
	if(FILE_MODE == SOCK_STREAM)
	{
		con_nw = create_network(cmd_nw);
		data_nw->fd = accept(con_nw->fd,(SP)&data_nw->addr,&con_nw->len);
		data_nw->type = FILE_MODE;
	}
	else
	{
		data_nw = create_network(cmd_nw);
	}
	
	
	system("ls -la > /tmp/list.txt");
	int fd = open("/tmp/list.txt",O_RDONLY);
	if(0 > fd)
	{
		perror("open");
		return;
	}
	
	int ret = 0;
	while(ret = read(fd,data_buf,sizeof(data_buf)))
	{
		printf("%s",data_buf);
		nsend(data_nw,data_buf,ret);
	}
	sleep(1);
	strcpy(cmd_buf,"list end");
	nsend(cmd_nw,cmd_buf,strlen(cmd_buf)+1);
	close_network(data_nw);
	close_network(con_nw);
}

void get_server(NetWork* cmd_nw,char* cmd_buf)
{
	char data_buf[1024] = {};
	
	NetWork* con_nw = create_network(cmd_nw);
	NetWork* data_nw = malloc(sizeof(NetWork));
	data_nw->fd = accept(con_nw->fd,(SP)&data_nw->addr,&con_nw->len);
	data_nw->type = SOCK_STREAM;
	
	int fd = open(cmd_buf+4,O_RDONLY);
	if(0 > fd)
	{
		perror("open");
		return;
	}
	
	int ret = 0;
	while(ret = read(fd,data_buf,sizeof(data_buf)))
	{
		nsend(data_nw,data_buf,ret);
	}
	close_network(data_nw);
	close_network(con_nw);
	
	if(NULL == file_md5(cmd_buf+4,data_buf))
	{
		perror("file md5 failed!\n");
		return;
	}
	strcpy(cmd_buf,"get end");
	strncat(cmd_buf,data_buf,16);
	nsend(cmd_nw,cmd_buf,strlen(cmd_buf)+1);	
}

void put_server(NetWork* cmd_nw,char* cmd_buf)
{
	char data_buf[1024] = {};
	
	NetWork* con_nw = create_network(cmd_nw);
	NetWork* data_nw = malloc(sizeof(NetWork));
	data_nw->fd = accept(con_nw->fd,(SP)&data_nw->addr,&con_nw->len);
	data_nw->type = SOCK_STREAM;
	
	int fd = open(cmd_buf+4,O_WRONLY|O_CREAT|O_TRUNC,0644);
	if(0 > fd)
	{
		perror("open");
		return;
	}
	
	int ret = 0;
	while(ret = nrecv(data_nw,data_buf,sizeof(data_buf)))
	{
		write(fd,data_buf,ret);
	}
	close_network(data_nw);
	close_network(con_nw);
	
	if(NULL == file_md5(cmd_buf+4,data_buf))
	{
		perror("file md5 failed!\n");
		return;
	}
	strcpy(cmd_buf,"put end");
	strncat(cmd_buf,data_buf,16);
	nsend(cmd_nw,cmd_buf,strlen(cmd_buf)+1);
}


void* start_run(void* arg)
{
	NetWork* cmd_nw = malloc(sizeof(NetWork));
	cmd_nw->fd = *(int*)arg;
	cmd_nw->type = SOCK_STREAM;

	char cmd_buf[256] = {};
	for(;;)
	{
		nrecv(cmd_nw,cmd_buf,sizeof(cmd_buf));
		if(0 == strncmp("list",cmd_buf,4))
		{
			list_server(cmd_nw,cmd_buf);
		}
		else if(0 == strncmp("get",cmd_buf,3))
		{
			get_server(cmd_nw,cmd_buf);
		}
		else if(0 == strncmp("put",cmd_buf,3))
		{
			put_server(cmd_nw,cmd_buf);
		}
		else if(0 == strncmp("quit",cmd_buf,4))
		{
			close_network(cmd_nw);
			return NULL;			
		}
		else
		{
			printf("-----cmd list-----\n");
			printf("list\n");
			printf("put filename\n");
			printf("get filename\n");
			printf("quit\n");
		}
	}
}

int main()
{
	NetWork* con_nw = open_network('s',SOCK_STREAM,SERVER_IP,PORT);
	if(NULL == con_nw)
	{
		printf("open_network error!\n");
		return -1;
	}

	for(;;)
	{
		struct sockaddr_in addrcli = {};
		int clifd = accept(con_nw->fd,(SP)&addrcli,&con_nw->len);
		if(0 > clifd)
		{
			perror("accept");
			sleep(1);
			continue;
		}
		pthread_t pid;
		pthread_create(&pid,NULL,start_run,&clifd);
		usleep(100);
	}
}
